#pragma once
#include "../../../include/net_interface.hpp"
#include "TimerManager.h"

class CP2P;

class ISession
{
public:
    virtual void OnEstablish(HNETHANDLE hHandle, HSESSION hSession) = 0;
    virtual void OnTerminate(HSESSION hSession) = 0;
    virtual void OnError(HNETHANDLE hHandle, HSESSION hSession, INT32 iModuleError, INT32 iSystemError) = 0;
    virtual void OnRecv(HSESSION hSession, const char* pData, const INT32 iLen) = 0;
};

class CHostSession :
    public ISession
{
public:
    CHostSession(CP2P* p2p);

    virtual void OnEstablish(HNETHANDLE hHandle, HSESSION hSession);
    virtual void OnTerminate(HSESSION hSession);
    virtual void OnError(HNETHANDLE hHandle, HSESSION hSession, INT32 iModuleError, INT32 iSystemError);
    virtual void OnRecv(HSESSION hSession, const char* pData, const INT32 iLen);

    void DisConnect(void);

    bool SendPkg(void* host);

    DEFMEMBER(HSESSION, m_session, session)
protected:
    CP2P*   m_p2p;
};

#define P2P_STAT_INT        0
#define P2P_STAT_CONNECTING 1
#define P2P_STAT_ESTABLISH  2
#define P2P_STAT_OK         3
#define P2P_STAT_ERROR      4

class CP2PSession :
    public ISession, public CTimer
{
public:
    CP2PSession(void);
    ~CP2PSession(void);

    void Reset(void);

    virtual void OnEstablish(HNETHANDLE hHandle, HSESSION hSession);
    virtual void OnTerminate(HSESSION hSession);
    virtual void OnError(HNETHANDLE hHandle, HSESSION hSession, INT32 iModuleError, INT32 iSystemError);
    virtual void OnRecv(HSESSION hSession, const char* pData, const INT32 iLen);
    virtual void OnTimer(void);

    bool Start(void);
    bool SendPkg(void* host);
    void DisConnect(void);

    bool Connect(void);

    //DEFMEMBER(void*, m_user_data, user_data)
    DEFMEMBER(CP2P*, m_p2p, p2p)
    DEFMEMBER(UINT32, m_p2p_id, p2p_id)
    DEFMEMBER(UINT32, m_local_ip, local_ip)
    DEFMEMBER(UINT16, m_local_port, local_port)
    DEFMEMBER(UINT32, m_peer_ip, peer_ip)
    DEFMEMBER(UINT16, m_peer_port, peer_port)
    DEFMEMBER(HNETHANDLE, m_net_handle, net_handle)
    DEFMEMBER(HSESSION,m_session, session)
    DEFMEMBER(UINT16, m_stat, stat)
    DEFMEMBER(HTIMER, m_timer, timer)
};

class CNATTestSession :
    public ISession
{
public:
    CNATTestSession(void);

    virtual void OnEstablish(HNETHANDLE hHandle, HSESSION hSession);
    virtual void OnTerminate(HSESSION hSession);
    virtual void OnError(HNETHANDLE hHandle, HSESSION hSession, INT32 iModuleError, INT32 iSystemError);
    virtual void OnRecv(HSESSION hSession, const char* pData, const INT32 iLen){};

    bool Test(UINT32 local_ip, UINT16 local_port, UINT32 peer_ip, UINT16 peer_port);
    bool SendPkg(void* host);

    DEFMEMBER(HSESSION, m_session, session)
    DEFMEMBER(CP2P*, m_p2p, p2p)
};

class CPunchSession :
    public ISession, public CTimer
{
public:
    virtual void OnEstablish(HNETHANDLE hHandle, HSESSION hSession);
    virtual void OnTerminate(HSESSION hSession);
    virtual void OnError(HNETHANDLE hHandle, HSESSION hSession, INT32 iModuleError, INT32 iSystemError);
    virtual void OnRecv(HSESSION hSession, const char* pData, const INT32 iLen);
    virtual void OnTimer(void);

    bool Punch(UINT32 peer_ip, UINT16 peer_port, INT32 count, INT32 elapse);

    bool Connect(void);

    DEFMEMBER(INT32, m_on_time_count, on_time_count)
    DEFMEMBER(HSESSION, m_session, session)
    DEFMEMBER(CP2P*, m_p2p, p2p)
    DEFMEMBER(UINT32, m_local_ip, local_ip)
    DEFMEMBER(UINT16, m_local_port, local_port)
    DEFMEMBER(UINT32, m_peer_ip, peer_ip)
    DEFMEMBER(UINT16, m_peer_port, peer_port)
};